/**
 *
 */
package com.storm.lib.base;

import java.util.ArrayList;
import java.util.List;


import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCountCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;

import com.storm.lib.template.GameDataTemplate;
import com.storm.lib.template.MemoryTemplate;
import com.storm.lib.util.DBUtil;
import com.storm.lib.util.ExceptionUtil;


/**
 * 类功能: DAO基类
 * @author johnny
 * @version 2010-10-28
 */
@Repository
public class BaseDAO {
	/**
	 * 得到hibernateTemplate
	 */
	@Autowired
	public HibernateTemplate hibernateTemplate;
	/**
	 * 得到jdbcTemplate
	 */
	@Autowired
	protected JdbcTemplate jdbcTemplate;
	@Autowired
	protected MemoryTemplate memoryTemplate;
	@Autowired
	protected GameDataTemplate gameCacheTemplate;
	protected final Logger logger = Logger.getLogger(getClass());
	/**
	 * 方法功能:
	 * 更新时间:2011-1-5, 作者:johnny
	 * @param string
	 * @return
	 */
	public void executeSql(String sql) {
		jdbcTemplate.execute(DBUtil.replaceDB(sql));
	}

	/**
	 * 方法功能:
	 * 更新时间:2011-1-5, 作者:johnny
	 * @param string
	 * @return
	 */
	public List dBfind(String string) {
		hibernateTemplate.clear();
		hibernateTemplate.setMaxResults(0);
		List list = hibernateTemplate.find(string);
		for (Object obj : list) {
			if(obj instanceof BasePo){
				((BasePo)obj).loadData(null);
			}
		}
		return list;
	}


	/**
	 *
	 * 方法功能:返回list
	 * 更新时间:2010-12-28, 作者:johnny
	 * @param clazz
	 * @return
	 */
	public List getDBList(Class clazz) {
		return dBfind("from "+clazz.getSimpleName());
	}

	/**
	 * 方法功能:根据条件返回list
	 * 更新时间:2010-12-28, 作者:johnny
	 * @param class1
	 * @param string
	 * @param id
	 * @return
	 */
	public List<BasePo> getListByIdCondition(Class clazz,String idField, Integer idValue) {
		List<BasePo> list =  dBfind("from "+clazz.getSimpleName()+" where "+idField+"="+idValue);
		for (int i = 0; i < list.size(); i++) {
			BasePo basePo = list.get(i);
		}
		return list;
	}

	/**
	 *
	 * 更新时间:2010-11-12, 作者:johnny
	 * 方法功能:插入对象 1.插数据库 2.同步到memcached
	 * @param rolePo
	 */
	public BasePo insert(BasePo basePo,BasePo assitPo) {
		basePo.saveData();
		hibernateTemplate.save(basePo);
		hibernateTemplate.evict(basePo);
		memoryTemplate.syncFromDB(basePo);
		basePo.loadData(assitPo);
		return basePo;
	}

	public BasePo insert(BasePo basePo) {
		return insert(basePo,null);
	}
	/**
	 * 直接插入到数据库
	 * @param basePo
	 * @return
	 */
	public BasePo insertToDB(BasePo basePo) {
		hibernateTemplate.save(basePo);
		hibernateTemplate.evict(basePo);
		return basePo;
	}

	/**
	 *
	 * 更新时间:2010-11-12, 作者:johnny
	 * 方法功能:插入对象 1.插数据库 2.同步到memcached
	 * @param rolePo
	 */
	public BasePo insert(BasePo basePo, boolean is2Mcc) {
		hibernateTemplate.save(basePo);
		hibernateTemplate.evict(basePo);
		if(is2Mcc)
			memoryTemplate.syncFromDB(basePo);

		return basePo;
	}

	/**
	 * 方法功能:删除记录
	 * 更新时间:2011-2-21, 作者:johnny
	 * @param tradePo
	 */
	public void remove(BasePo basePo) {
		String hql = "Delete from "+basePo.getClass().getSimpleName()+" where id="+basePo.getId();
		hibernateTemplate.bulkUpdate(hql);
		memoryTemplate.removeKey(basePo);
	}

	/**
	 *
	 * 更新时间:2010-10-28, 作者:johnny
	 * 方法功能:返回实体
	 * @param id
	 * @return
	 */
	public BasePo getEntityPo(Integer id,Class clz) {
		if(id==null){
			return null;
		}
		if(clz.getSuperclass().getSimpleName().equals(BaseGameDBPo.class.getSimpleName())){
			return gameCacheTemplate.getGameData(clz, id);
		}
		BasePo basePo = (BasePo) memoryTemplate.get(id,clz);
		if(basePo==null){
			basePo =(BasePo) hibernateTemplate.get(clz, id);
			if(basePo==null){
				return null;
			}
			else{
				hibernateTemplate.evict(basePo);
				memoryTemplate.syncFromDB(basePo);
				if(basePo instanceof BaseUserDBPo){
					BaseUserDBPo baseUserDBPo = (BaseUserDBPo) basePo;
					baseUserDBPo.loadData(null);
				}
				return basePo;
			}
		}
		else{
			basePo.loadData(null);
			return basePo;
		}
	}

	/**
	 *
	 * 更新时间:2010-10-28, 作者:johnny
	 * 方法功能:返回实体
	 * @param id
	 * @return
	 */
	public BasePo getEntityById(BasePo basePo) {
		basePo = (BasePo) getEntityPo(basePo.getId(),basePo.getClass());
		return basePo;
	}

	/**
	 *
	 * 方法功能:更新实体
	 * 更新时间:2010-11-2, 作者:johnny
	 * @param basePo 实体
	 * @param propertiName 属性名
	 * @param parameter 参数
	 * @return
	 */
//	public Object updateEntityProperties(BasePo basePo,String propertiName,Object parameter) {
//		try{
//			if(basePo==null || basePo.getId()==null){
//				ExceptionUtil.throwInvalidParamException();
//			}
////			basePo =(BasePo) hibernateTemplate.get(basePo.getClass(), basePo.getId());
//			hibernateTemplate.evict(basePo);
//			basePo = updateEntity(basePo, propertiName, parameter);
//			return basePo;
//		}catch (Exception e) {
//			ExceptionUtil.processException(e);
//		}
//		ExceptionUtil.throwInvalidParamException();
//		return basePo;
//	}

	/**
	 *
	 * 方法功能:更新实体的实际代码
	 * 更新时间:2010-11-2, 作者:johnny
	 * @param basePo
	 * @param propertiName
	 * @param parameter
	 * @return true更新成功
	 * @throws Exception
	 */
	private BasePo updateEntity(BasePo basePo, String propertiName,Object parameter) throws Exception {
		if(basePo==null){
			ExceptionUtil.throwInvalidParamException();
		}
//		String className = basePo.getClass().getSimpleName();
//		int result=hibernateTemplate.bulkUpdate("Update "+className+" Set "+propertiName+"=? where id=?", new Object[]{parameter,basePo.getId()});
//		if(result>=1){
		basePo.setProperty(propertiName, parameter);
		hibernateTemplate.evict(basePo);
		memoryTemplate.put(basePo);
		return basePo;
//		}
//		return basePo;

	}

	/**
	 *
	 * 方法功能:更新实体的实际代码
	 * 更新时间:2011-1-11, 作者:johnny
	 * @param basePo
	 * @return
	 * @throws Exception
	 */
	public BasePo updateEntity(BasePo basePo){
		if(basePo==null){
			ExceptionUtil.throwInvalidParamException();
		}
//		String className = basePo.getClass().getSimpleName();
//		int result=hibernateTemplate.bulkUpdate("Update "+className+" Set "+propertiName+"=? where id=?", new Object[]{parameter,basePo.getId()});
//		if(result>=1){
//		basePo.setProperty(basePo, propertiName, parameter);
		hibernateTemplate.evict(basePo);
		memoryTemplate.put(basePo);
		return basePo;
//		}
//		return basePo;
	}

	/**
	 *
	 * 方法功能:更新实体的实际代码
	 * 更新时间:2011-1-11, 作者:johnny
	 * @param basePo
	 * @return
	 * @throws Exception
	 */
	public void updateEntityToDB(BasePo basePo){
		if(basePo==null){
			ExceptionUtil.throwInvalidParamException();
		}
		hibernateTemplate.update(basePo);
		hibernateTemplate.evict(basePo);
	}


	/**
	 *
	 * 更新时间:2010-11-21, 作者:johnny
	 * 方法功能:返回数组
	 * @param ids
	 * @param clazz
	 * @param ignoreNomatchItem 若为true,则遇到不匹配的记录直接跳过
	 * @return
	 */
	public BasePo[] getArrayByIds(int[] ids,Class clazz,boolean ignoreNomatchItem){
		if(ids==null || ids.length==0){
			ExceptionUtil.throwInvalidParamException();
		}
		List<BasePo> list =new ArrayList<BasePo>();
		for (int i = 0; i < ids.length; i++) {
			BasePo basePo = getEntityPo(ids[i], clazz);
			if(basePo==null){
				if(ignoreNomatchItem){
					continue;
				}
				else{
					list.add(null);
				}
			}
			else{
				list.add(basePo);
			}
		}
		return list.toArray(new BasePo[list.size()]);
	}


	/**
	 * 方法功能:判断是否内存已经有这个对象
	 * 更新时间:2010-12-29, 作者:johnny
	 * @param class1
	 * @param id
	 * @return
	 */
	public Boolean hasMemory(Class clazz, int id) {
		return memoryTemplate.has(clazz, id);
	}

	/**
	 * 方法功能:直接从内存返回数据
	 * 更新时间:2010-12-29, 作者:johnny
	 * @param class1
	 * @param id
	 * @return
	 */
	public BasePo getFromMemory(Class clazz, int id) {
		return memoryTemplate.get(id, clazz);
	}

	/**
	 * 方法功能:和内存值关联
	 * 更新时间:2010-12-29, 作者:johnny
	 * @param heroPo
	 */
	public void linkToMemory(BasePo basePo) {
		memoryTemplate.put(basePo);
	}



	/**
	 *
	 * 方法功能:返回根据条件的指定对象
	 * 更新时间:2011-1-4, 作者:johnny
	 * @param clazz
	 * @param idField
	 * @param idValue
	 * @return
	 */
	public BasePo getObjectByCondition(Class clazz,String idField, Object obj) {
		String value="";
		value = DBUtil.getSqlValueByType(obj);
		String hql = "from "+clazz.getSimpleName()+" where "+idField+"="+value;
		BasePo basePo  =  getFirstResult(hql);
		if(basePo!=null){
			if(hasMemory(basePo.getClass(), basePo.getId())){
				return getFromMemory(basePo.getClass(), basePo.getId());
			}
			else{
				basePo.loadData(null);
				linkToMemory(basePo);
			}
		}
		return basePo;
	}

	/**
	 * 方法功能:返回指定的hql结果
	 * 更新时间:2011-1-4, 作者:johnny
	 * @param hql
	 * @return
	 */
	protected BasePo getFirstResult(String hql) {
		hibernateTemplate.setMaxResults(1);
		List<BasePo> list = dBfind(hql);
		hibernateTemplate.evict(list);
		if(list.size()>0){
			hibernateTemplate.setMaxResults(0);
			return list.get(0);
		}
		hibernateTemplate.setMaxResults(0);
		return null;
	}



	public void batchUpdate(String[] array) {
		for (int i = 0; i < array.length; i++) {
			array[i]=DBUtil.replaceDB(array[i]);
		}
		jdbcTemplate.batchUpdate(array);
	}

	/**
	 * 方法功能:查询int
	 * 更新时间:2011-3-7, 作者:johnny
	 * @param string
	 * @return
	 */
	public Integer queryIntForSql(String sql) {
		List<Integer> ints = jdbcTemplate.queryForList(DBUtil.replaceDB(sql.concat(" limit 1")), Integer.class);
		if(ints.size()==0){
			return null;
		}
		return ints.get(0);
	}

	public List querySql(RowMapper rowMapper,String sql) {
		sql=DBUtil.replaceDB(sql);
		return jdbcTemplate.query(sql, rowMapper);
	}

	public void syncToDB(BasePo basePo) {
		memoryTemplate.syncToDB(basePo);
	}

	public void syncToDB(List<BasePo> list) {
		memoryTemplate.syncToDB(list);
	}

	public void loadAll(List<BasePo> list) {
		for (BasePo basePo : list) {
			basePo.loadData(null);
		}
	}
	/**
	 * 获得表字段
	 * @param sql
	 * @return
	 */
	public String[] getColumnNames(String sql){
		RowCountCallbackHandler rcch = new RowCountCallbackHandler();
		jdbcTemplate.query(sql, rcch);
		String[] columns = rcch.getColumnNames();
		return columns;
	}

}
